import React, { useEffect, useState } from 'react';
import { Select, Checkbox } from 'antd';
import styles from './index.less';

const SigleSelect = (props) => {
  return (
    <Select
      allowClear={false}
      showArrow={true}
      style={{ width: 160 }}
      optionFilterProp="label"
      getPopupContainer={(e) => e.parentNode}
      {...props}
    />
  );
};

const MultiSelect = (props) => {
  const { mode, value = [], options, onChange, label = '', ...other } = props;
  const allLen = options.length;
  const allVal = options.map((x) => x.value);

  const [checked, setChecked] = useState([]);
  const [indeterminate, setIndeterminate] = useState(false);
  const [checkedAll, setCheckedAll] = useState(true);

  useEffect(() => {
    changeChecked(value);
  }, [JSON.stringify(value), JSON.stringify(options)]);

  const changeChecked = (vals) => {
    const len = vals.length;
    setCheckedAll(len > 0 && len === allLen);
    setIndeterminate(len > 0 && len < allLen);
    setChecked(vals);
  };

  return (
    <Select
      value={
        !value.length || value.length === allLen
          ? `全部${label}`
          : `${value.length}/${allLen}项${label}`
      }
      allowClear={false}
      showArrow={true}
      style={{ width: 160 }}
      optionFilterProp="label"
      getPopupContainer={(e) => e.parentNode}
      dropdownClassName={styles.dropdown}
      dropdownRender={() => (
        <>
          <Checkbox
            checked={checkedAll}
            indeterminate={indeterminate}
            onChange={(e) => {
              const all = e.target.checked;
              setCheckedAll(all);
              setIndeterminate(false);
              setChecked(all ? [...allVal] : []);
            }}
          >
            全选
          </Checkbox>
          <Checkbox.Group value={checked} options={options} onChange={changeChecked} />
        </>
      )}
      onDropdownVisibleChange={(open) => {
        // 关闭时再赋值
        if (!open) {
          const changeValue = [...(!checked.length ? allVal : checked)];
          if (JSON.stringify(value) !== JSON.stringify(changeValue)) {
            onChange?.(changeValue);
          }
        }
      }}
      {...other}
    />
  );
};

const MultipleTagsSelect = (props) => {
  const { mode, value = [], options, onChange, label = '', ...other } = props;
  const allLen = options.length;
  const allVal = options.map((x) => x.value);

  const [checked, setChecked] = useState([]);
  const [indeterminate, setIndeterminate] = useState(false);
  const [checkedAll, setCheckedAll] = useState(true);

  useEffect(() => {
    changeChecked(value);
  }, [JSON.stringify(value), JSON.stringify(options)]);

  const changeChecked = (vals) => {
    const len = vals.length;
    setCheckedAll(len > 0 && len === allLen);
    setIndeterminate(len > 0 && len < allLen);
    setChecked(vals);
  };

  return (
    <Select
      value={value}
      allowClear={false}
      showArrow={true}
      style={{ width: 160 }}
      optionFilterProp="label"
      mode={'multiple'}
      options={options}
      getPopupContainer={(e) => e.parentNode}
      dropdownClassName={styles.dropdown}
      onChange={onChange}
      dropdownRender={() => (
        <>
          <Checkbox
            checked={checkedAll}
            indeterminate={indeterminate}
            onChange={(e) => {
              const all = e.target.checked;
              setCheckedAll(all);
              setIndeterminate(false);
              setChecked(all ? [...allVal] : []);
            }}
          >
            全选
          </Checkbox>
          <Checkbox.Group value={checked} options={options} onChange={changeChecked} />
        </>
      )}
      onDropdownVisibleChange={(open) => {
        // 关闭时再赋值
        if (!open) {
          const changeValue = [...(!checked.length ? allVal : checked)];
          if (JSON.stringify(value) !== JSON.stringify(changeValue)) {
            onChange?.(changeValue);
          }
        }
      }}
      {...other}
    />
  );
};

export default (props) => {
  const { mode, options, fieldNames, ...others } = props;
  const myProps = {
    mode,
    options: options.map((x) => {
      // 选项重构，1.文本数组、2.支持fieldNames属性
      if (typeof x === 'string') return { label: x, value: x };
      if (!!fieldNames) {
        return { label: x?.[fieldNames?.label], value: x?.[fieldNames?.value], ...x };
      }
      return x;
    }),
    ...others,
  };
  if (mode === 'multiple') {
    return MultiSelect(myProps);
  } else if (mode === 'multipleTags') {
    return MultipleTagsSelect(myProps);
  }
  return SigleSelect(myProps);
};
